package com.zqc.controller;


import cn.hutool.core.map.MapUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zqc.common.dto.PasswordDto;
import com.zqc.common.lang.Const;
import com.zqc.common.lang.Result;
import com.zqc.entity.SysRole;
import com.zqc.entity.SysUser;
import com.zqc.entity.SysUserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zqc
 * @since 2023-03-07
 */
@RestController
@RequestMapping("/sys/users")
public class SysUserController extends BaseController {

    @Autowired
    public BCryptPasswordEncoder passwordEncoder;

    /**
     * 前端页面头部获取当前登录用户的信息
     *
     * @param principal
     * @return
     */
    @GetMapping("/info")
    public Result info(Principal principal) {
        SysUser user = sysUserService.getUserByUsername(principal.getName());
        return Result.succ(
                MapUtil.builder()
                        .put("id", user.getId())
                        .put("username", user.getUsername())
                        .put("avatar", user.getAvatar())
                        .map()
        );
    }

    /**
     * 前端用户管理模块获取单个用户的信息
     *
     * @param userId
     * @return
     */
    @GetMapping("/info/{userId}")
    @PreAuthorize("hasAuthority('sys:user:list')")
    public Result info(@PathVariable(name = "userId") Long userId) {
        // 获取用户信息
        SysUser user = sysUserService.getById(userId);
        // 捕获异常
        Assert.notNull(user, "找不到该管理员");

        // 获取用户所拥有的角色
        List<SysRole> roles = sysRoleService.listRolesByUserId(userId);

        user.setRoles(roles);
        return Result.succ(user);
    }

    @GetMapping("/list")
    @PreAuthorize("hasAuthority('sys:user:list')")
    public Result list(String username) {
        Page<SysUser> page = sysUserService.page(getPage(), new LambdaQueryWrapper<SysUser>()
                .like(username != null, SysUser::getUsername, username));

        // 获取用户关联的角色信息
        page.getRecords().forEach(u -> {
            u.setRoles(sysRoleService.listRolesByUserId(u.getId()));
        });

        return Result.succ(page);
    }

    @PostMapping("/save")
    @PreAuthorize("hasAuthority('sys:user:save')")
    public Result save(@Validated @RequestBody SysUser user) {
        // 设置默认属性
        user.setCreated(LocalDateTime.now());
        user.setStatus(Const.ROLE_STATUS_ON);
        user.setAvatar(Const.DEFAULT_AVATAR);
        user.setPassword(passwordEncoder.encode(Const.DEFAULT_PASSWORD));

        sysUserService.save(user);

        return Result.succ(user);
    }

    @PostMapping("/update")
    @PreAuthorize("hasAuthority('sys:user:update')")
    public Result update(@Validated @RequestBody SysUser user) {
        user.setUpdated(LocalDateTime.now());
        sysUserService.updateById(user);

        // 清空该用户相关的权限缓存
        sysUserService.clearUserAuthorityInfoByUsername(user.getUsername());

        return Result.succ(user);
    }

    @Transactional
    @PostMapping("/delete")
    @PreAuthorize("hasAuthority('sys:user:delete')")
    public Result delete(@RequestBody Long[] userIds) {

        // 删除相关表信息
        sysUserService.removeByIds(Arrays.asList(userIds));
        userRoleService.remove(new QueryWrapper<SysUserRole>().in("user_id", userIds));

        return Result.succ("删除用户成功");
    }

    /**
     * 给用户分配角色
     *
     * @param userId
     * @return
     */
    @Transactional
    @PostMapping("/role/{userId}")
    @PreAuthorize("hasAuthority('sys:user:role')")
    public Result rolePerm(@PathVariable(name = "userId") Long userId, @RequestBody Long[] roleIds) {
        List<SysUserRole> userRoles = new ArrayList<>();
        Arrays.stream(roleIds).forEach(roleId -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setRoleId(roleId);
            sysUserRole.setUserId(userId);

            userRoles.add(sysUserRole);
        });

        // 删除相关信息在保存
        userRoleService.remove(new QueryWrapper<SysUserRole>().eq("user_id", userId));
        userRoleService.saveBatch(userRoles);

        // 清空redis中与该用户先关的缓存
        SysUser user = sysUserService.getById(userId);
        sysUserService.clearUserAuthorityInfoByUsername(user.getUsername());

        return Result.succ("分配角色成功");
    }

    @PostMapping("/repass/{userId}")
    @PreAuthorize("hasAuthority('sys:user:repass')")
    public Result rePassword(@PathVariable(name = "userId") Long userId) {
        SysUser user = sysUserService.getById(userId);
        // 设置属性
        user.setUpdated(LocalDateTime.now());
        user.setPassword(passwordEncoder.encode(Const.DEFAULT_PASSWORD));
        sysUserService.updateById(user);
        return Result.succ("重置密码成功");
    }

    @PostMapping("/updatePass")
    public Result rePassword(@Validated @RequestBody PasswordDto passwordDto, Principal principal) {
        // 获取当前用户信息
        SysUser user = sysUserService.getUserByUsername(principal.getName());

        // 校验密码是否正确
        boolean matches = passwordEncoder.matches(passwordDto.getCurrentPass(), user.getPassword());
        if (!matches) {
            return Result.fail("旧密码错误！");
        }

        // 设置更新时间和密码
        user.setUpdated(LocalDateTime.now());
        user.setPassword(passwordEncoder.encode(passwordDto.getPassword()));
        // 更新用户密码
        sysUserService.updateById(user);

        return Result.succ(user);
    }

}
